#include "rs485_v3.hpp"

// struct gpiod_chip *m_gpioChip_p;
// struct gpiod_line *m_deLine;
// std::string m_lastError;
// std::string m_gpioChip = "/dev/gpiochip3";
// uint32_t m_dePinOffset = 23;

bool rs485_v3::_init_de_pin()
{
    if (_flag == YJ_OK)
    {
        LOG(WARNING) << "[rs485_v3][_init_de_pin] already inited, skip...";
        return true;
    }
    _gpioChip_p = gpiod_chip_open(_gpioChip.c_str());
    if (!_gpioChip_p)
    {
        LOG(ERROR) << "[rs485_v3][_init_de_pin][gpioChip: " << _gpioChip << "]"
                   << "[dePinOffset: " << _dePinOffset << "]"
                   << " Failed to open GPIO chip";
        return false;
    }

    // 获取GPIO线
    _deLine = gpiod_chip_get_line(_gpioChip_p, _dePinOffset);
    if (!_deLine)
    {
        LOG(ERROR) << "[rs485_v3][_init_de_pin][gpioChip: " << _gpioChip << "]"
                   << "[dePinOffset: " << _dePinOffset << "]"
                   << " Failed to get GPIO line";
        gpiod_chip_close(_gpioChip_p);
        _gpioChip_p = nullptr;
        return false;
    }

    // 检查当前线路状态
    if (gpiod_line_is_used(_deLine))
    {
        LOG(ERROR) << "[rs485_v3][_init_de_pin][gpioChip: " << _gpioChip << "]"
                   << "[dePinOffset: " << _dePinOffset << "]"
                   << " GPIO line is currently in use,try to release it ";

        _deLine = gpiod_chip_get_line(_gpioChip_p, _dePinOffset);

        gpiod_line_release(_deLine);
        // gpiod_chip_close(_gpioChip_p);
        // _gpioChip_p = nullptr;
        // return false;

        // std::cout << "Debug: GPIO line is currently in use, attempting to release..." << std::endl;
        // gpiod_line_release(m_deLine);
    }

    std::string pin_name = _uart->uart_get_port_name() + "rs485_de";
    // 配置GPIO为输出模式，初始状态为低电平（接收模式）
    struct gpiod_line_request_config config = {
        .consumer = pin_name.c_str(),
        .request_type = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT,
        .flags = 0,
    };

    if (gpiod_line_request(_deLine, &config, 0) < 0)
    {
        LOG(ERROR) << "[rs485_v3][_init_de_pin][gpioChip: " << _gpioChip << "]"
                   << "[dePinOffset: " << _dePinOffset << "]"
                   << " Failed to request GPIO line ";
        // m_lastError = "Failed to request GPIO line: " + std::string(strerror(errno));
        // std::cout << "Debug: " << m_lastError << std::endl;
        gpiod_chip_close(_gpioChip_p);
        _gpioChip_p = nullptr;
        return false;
    }

    // 确认GPIO设置成功
    int current_value = gpiod_line_get_value(_deLine);
    // LOG(INFO) << "[rs485_v3][_init_de_pin][gpioChip: " << _gpioChip << "]"
    //            << "[dePinOffset: " << _dePinOffset << "]"
    //            << "Initial GPIO value: " << current_value;

    return true;
}

bool rs485_v3::_deinit_de_pin()
{
    // std::cout << "Debug: Releasing DE/RE pin..." << std::endl;
    if (_deLine)
    {
        gpiod_line_release(_deLine);
        _deLine = nullptr;
    }
    if (_gpioChip_p)
    {
        gpiod_chip_close(_gpioChip_p);
        _gpioChip_p = nullptr;
    }
    return true;
}

// 发送设置允许设置后延时以保证发送电平稳定，但接收设置在发送完成后要求以最快速度执行
void rs485_v3::_set_transmit()
{
    int ret = gpiod_line_set_value(_deLine, 1);
}

void rs485_v3::_set_receive()
{
    int ret = gpiod_line_set_value(_deLine, 0);
}

rs485_v3::rs485_v3(uart_v2 *uart,
                   std::string gpioChip,
                   uint32_t dePinOffset,
                   uint32_t frame_timeout_ms = 100) : _uart(uart),
                                                      _gpioChip(gpioChip),
                                                      _dePinOffset(dePinOffset),
                                                      _frame_timeout_ms(frame_timeout_ms)
{
    _deLine = nullptr;
    _gpioChip_p = nullptr;
    _mode = RS485_V3_MANUAL_DE_CONTROL_MODE;
    _flag = YJ_ERROR;
}

rs485_v3::rs485_v3(uart_v2 *uart,
                   uint32_t frame_timeout_ms) : _uart(uart),
                                                _frame_timeout_ms(frame_timeout_ms)
{
    _deLine = nullptr;
    _gpioChip_p = nullptr;
    _mode = RS485_V3_AUTO_DE_CONTROL_MODE;
    _flag = YJ_ERROR;
}

rs485_v3::~rs485_v3()
{
    rs485_close();
}

yj_return rs485_v3::rs485_open()
{
    yj_return ret = YJ_OK;
    if (!_uart)
    {
        ret = YJ_ERROR;
        return ret;
    }

    switch (_mode)
    {
    case RS485_V3_MANUAL_DE_CONTROL_MODE:
        if (_init_de_pin() != true)
            ret = YJ_ERROR;
        break;
    case RS485_V3_AUTO_DE_CONTROL_MODE:
        break;
    default:
        LOG(ERROR) << "485 [ " << _uart->uart_get_port_name() << " ] mode error ";
        break;
    }

    if (_uart->uart_open() != YJ_OK)
        ret = YJ_ERROR;
    _flag = ret;
    return ret;
}

yj_return rs485_v3::rs485_close()
{

    _uart->uart_close();
    if (_mode == RS485_V3_MANUAL_DE_CONTROL_MODE)
    {
        _deinit_de_pin();
    }
    return YJ_OK;
}

int rs485_v3::rs485_send(const uint8_t *buf, int len)
{
    uint32_t ret = 0;
    // std::string data_str;
    // for (int i = 0; i < len; i++)
    // {
    //     std::ostringstream sstr;
    //     sstr << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << static_cast<int>(buf[i]) << " ";
    //     data_str += sstr.str();
    // }
    // data_str += " data size: " + std::to_string(len);
    // LOG(INFO) << "485 send msg: " << data_str;

    switch (_mode)
    {
    case RS485_V3_MANUAL_DE_CONTROL_MODE:
        _set_transmit();
        ret = _uart->uart_send(buf, len);
        _set_receive();
        break;
    case RS485_V3_AUTO_DE_CONTROL_MODE:
        ret = _uart->uart_send(buf, len);
        break;

    default:
        LOG(ERROR) << "485 [ " << _uart->uart_get_port_name() << " ] mode error ";
        break;
    }
    return ret;
}

int rs485_v3::rs485_recv(uint8_t *buf, int max_len)
{
    int len;
    // _set_receive();
    // len = _uart->uart_recv(buf, max_len);
    len = _uart->uart_recv_one_by_one(buf, max_len, _frame_timeout_ms);

    // std::string data_str;
    // for (int i = 0; i < len; i++)
    // {

    //     std::ostringstream sstr;
    //     sstr << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << static_cast<int>(buf[i]) << " ";
    //     data_str += sstr.str();
    // }
    // data_str += " data size: " + std::to_string(len);
    // LOG(INFO) << "485 recv msg: " << data_str;

    return len;
}

int rs485_v3::rs485_recv_with_length(uint8_t *buf, int len)
{
    int len_b = _uart->uart_recv(buf, len);
    // std::string data_str;
    // for (int i = 0; i < len_b; i++)
    // {
    //     std::ostringstream sstr;
    //     sstr << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << static_cast<int>(buf[i]) << " ";
    //     data_str += sstr.str();
    // }
    // data_str += " data size: " + std::to_string(len_b);
    // LOG(INFO) << "485 recv with length msg: " << data_str;

    return len_b;
}

rs485_v3 &rs485_v3::rs485_change_baud_rate(int baud_rate)
{
    _uart->uart_change_baud_rate(baud_rate);
    return *this;
}

rs485_v3 &rs485_v3::rs485_change_send_additonal_byte_time(float additonal_byte_time)
{
    _uart->uart_change_send_additonal_btye_time(additonal_byte_time);
    return *this;
}
void rs485_v3::rs485_flush_all()
{
    _uart->uart_flush_all();
}

std::mutex& rs485_v3::rs485_get_mutex()
{
    return _uart->uart_get_mutex();
}

yj_return rs485_v3::rs485_get_flag()
{
    return _flag;
}